package donnees;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class FabriqueProduit {

	public static FabriqueProduit fc = null;
	private Map<Integer, Produit> cache;
	private Connection dbCon;
	private PreparedStatement creer;
	private PreparedStatement rechercherProduit;
	private PreparedStatement listerProduit;
	private PreparedStatement recupererDernierID;
	

	public static FabriqueProduit getInstance() throws SQLException {
		if (fc == null) {
			fc = new FabriqueProduit();
		}
		return fc;
	}

	private FabriqueProduit() throws SQLException {
		this.cache = new HashMap<Integer, Produit>();
		this.initConnection();
	}

	private void initConnection() throws SQLException {
		this.dbCon = DB.getInstance().getConnection();
		this.creer = dbCon
				.prepareStatement("INSERT INTO Produit(idproduit,nom,description,prix,stock,delaidispo,delainondispo,urlimage) VALUES(NEXT VALUE FOR produit_seq,?,?,?,?,?,?,?)");
		this.rechercherProduit = dbCon
				.prepareStatement("SELECT idProduit,nom,description,prix,stock,delaidispo,delainondispo,urlimage FROM Produit WHERE idproduit=?");
		this.listerProduit = dbCon
				.prepareStatement("SELECT idProduit From Produit");
	
		// IDENTITY uniquement pour des colonnes identity et non les sequence
		// Pas non plus de fonction pour récupérer dernière valeur d'une sqce dans hsqldb ...
		//this.recupererDernierID = dbCon.prepareStatement("CALL IDENTITY()");
		
		this.recupererDernierID = dbCon.prepareStatement("SELECT max(idproduit) FROM produit");
		
	}

	// creer
	public Produit creer(String nom, String description, double prix,
			int stock, int delaidispo, int delainondispo, String urlimage)
			throws SQLException {
		// tester les données
		boolean flag = true;
		if (nom == null || nom.equals("") || nom.length() > 40)
			flag = false;
		if (description == null || description.equals("")
				|| description.length() > 1000)
			flag = false;
		if (prix < 0)
			flag = false;
		if (stock < 0)
			flag = false;
		if (urlimage == null || urlimage.equals("") || urlimage.length() > 250)
			flag = false;
		// insérer le nouveau Produit
		if (flag) {
			creer.clearParameters();
			creer.setString(1, nom);
			creer.setString(2, description);
			creer.setDouble(3, prix);
			creer.setInt(4, stock);
			creer.setInt(5, delaidispo);
			creer.setInt(6, delainondispo);
			creer.setString(7, urlimage);
			creer.executeUpdate();
			// récupérer son id et créer un objet Produit à retourner
			ResultSet retour = recupererDernierID.executeQuery();
			retour.next();
			Produit leProduit = new Produit(retour.getInt(1), nom, description,
					prix, stock, delaidispo, delainondispo, urlimage);
			cache.put(retour.getInt(1), leProduit);
			return leProduit;
		} else {
			return null;
		}

	}

	// rechercher
	public Produit rechercher(Integer idProduit) throws SQLException {
		if (cache.containsKey(idProduit)) {
			return cache.get(idProduit);
		} else {
			rechercherProduit.clearParameters();
			rechercherProduit.setInt(1, idProduit);
			ResultSet retour = rechercherProduit.executeQuery();
			if (retour.next()) {
				Produit leProduit = new Produit(idProduit, retour.getString(2),
						retour.getString(3), retour.getDouble(4),
						retour.getInt(5), retour.getInt(6), retour.getInt(7),
						retour.getString(8));
				cache.put(idProduit, leProduit);
				return leProduit;
			}
			return null;
		}
	}

	// lister
	public Collection<Produit> lister() throws SQLException {
	
		ResultSet result = listerProduit.executeQuery();
		// hashmap values => not serializable, obligatoirement récreer une nouvelle collection
		Collection<Produit> retour = new ArrayList<Produit>();

		Produit prod;
		Integer id;
		while(result.next()) {
			id = result.getInt(1);			
			if (!cache.containsKey(id)) {
				prod = rechercher(id);
				cache.put(id, prod);
				retour.add(prod);
			}
			retour.add(cache.get(id));
		}
		return retour;
	}

	// viderCache
	public void flushCache() {
		this.cache.clear();
	}
}
